/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package simco.framework.gui.graph;

import java.awt.Graphics2D;
import java.util.ArrayList;
import java.util.List;

import simco.framework.gui.graph.base.GraphRectangle;
import simco.framework.gui.graph.supp.BorderType;
import simco.framework.gui.graph.supp.ComponentType;
import simco.framework.gui.graph.supp.ViewModeType;
import simco.framework.gui.services.IMethodInfoProvider;
import simco.framework.gui.utils.Configuration;
import simco.framework.models.MethodInfo;

/**
 * Trida slouzici k reprezentaci komponponenty v simulaci
 * k vizualizaci na grafickem platne.
 *  
 * @author Matej Prokop, mythge@students.zuc.cz
 */
public class UsedComponent extends GraphRectangle
{
	/**
	 * Typ komponenty
	 */
    private ComponentType type;

    /**
     * Reference na objekt poskytujici informace o metodach komponenty
     */
    private IMethodInfoProvider methodInfoProvider;
    
    /**
     * List uchovavajici seznam metod poskytovanych komponentou
     */
    public List<String> methodsList;
    
    /**
     * Vraci novou instanci objektu slouziciho k vizualizaci komponenty.
     * 
     * @param objectId identifikator komponenty 
     * @param name nazev komponenty
     * @param type typ komponenty
     * @param mip objekt poskytujici informace o metodach komponenty
     */
    public UsedComponent(long objectId, String name, ComponentType type,
    		IMethodInfoProvider mip)
    {
        super(objectId, name);
        this.type = type;

        if(this.type == ComponentType.SIMULATION)
        {
            this.setBorderType(BorderType.DASHED);
        }
        
        this.methodInfoProvider = mip;
        this.methodsList = new ArrayList<String>();
        retraiveMethodList();
    }
    
    /**
     * Nacte seznam metod poskytovanych komponentou
     */
    private void retraiveMethodList()
    {
    	methodsList.clear();
    	for(MethodInfo mi : methodInfoProvider.getMethods(getId()))
    	{
    		methodsList.add(mi.getClassName() + "." + mi.getMethodName() + "()");
    	}
    }
    
    /**
     * Vypocte potrebnou velikost komponenty (obdelniku) na platne,
     * tak aby se do nej vesli vsechny zobrazovane informace.
     */
    private void computeSize()
    {    	
    	switch (this.viewMode) 
    	{
			case MINIMAL:				
				setSize(2 * INSETS_SIZE + fontMetrick.stringWidth(getObjectTitle()),
						2 * INSETS_SIZE + fontMetrick.getHeight());				
				break;
			case DETAIL:
				measureSizeForDetail();
				break;
			default:
				int maxWidth = Math.max(fontMetrick.stringWidth(getObjectTitle()), 
						fontMetrick.stringWidth("Typ: " + this.type));
				setSize(2 * INSETS_SIZE + maxWidth,
						2 * INSETS_SIZE + 2 * fontMetrick.getHeight());	
				break;
		}
    }
    
    /**
     * Vypocet potrebnou velikost komponenty (obdelniku) na platne,
     * tak aby se do nej vesli vsechny zobrazovane informace ve
     * chvili, kdy je komponenta zobrazovana v deatilnim zobrazovacim
     * modu.
     */
    private void measureSizeForDetail()
    {
		int maxWidth = Math.max(fontMetrick.stringWidth(getObjectTitle()), 
				fontMetrick.stringWidth("Type: " + this.type));
		
		for(String s : this.methodsList)
    	{
			maxWidth = Math.max(maxWidth, fontMetrick.stringWidth(s));
    	}
		
		setSize(2 * INSETS_SIZE + maxWidth,
				2 * INSETS_SIZE + (2 + 1 + methodsList.size()) * fontMetrick.getHeight());	   	
    }
    
    @Override
	public void setViewMode(ViewModeType newViewMode) 
    {
		this.viewMode = newViewMode;
		computeSize();
	}

	@Override
    public void drawObject(Graphics2D g2)
    {
        super.drawObject(g2);

        if(this.viewMode != ViewModeType.MINIMAL)
        {
        	g2.setFont(NORMAL_FONT);
        	
        	g2.drawString("Typ: " + this.type, Configuration.INSETS_SIZE + this.getX(),
        			this.getY() + fontMetrick.getHeight());        	
        }

        g2.setFont( BOLD_FONT );
        
        // vizualizace nazvu objektu
        if(this.viewMode != ViewModeType.MINIMAL)
        {
        	g2.drawString(objectTitle, this.getMidX() - fontMetrick.stringWidth(objectTitle) / 2,
        			this.getY() + INSETS_SIZE + fontMetrick.getHeight() * 1.75f);        	
        }
        else
        {
        	g2.drawString(objectTitle, this.getMidX() - fontMetrick.stringWidth(objectTitle) / 2,
        			this.getMidY() + fontMetrick.getAscent() /2);
        }
        
        g2.setFont( NORMAL_FONT );
        
        if(this.viewMode == ViewModeType.DETAIL)
        {
        	g2.setFont(NORMAL_FONT);
        	
        	int yCord = INSETS_SIZE;
        	for(String s : this.methodsList)
        	{
        		g2.drawString(s, this.getX() + INSETS_SIZE,
        				this.getMaxY() - yCord);
        		yCord += fontMetrick.getHeight();
        	}
        	
	        g2.drawString("Metody:", this.getX() + Configuration.INSETS_SIZE,
	                this.getMaxY() - yCord);
	        
        }
    }
    
	/**
	 * Vraci typ komponenty
	 * @return typ komponenty
	 */
    public ComponentType getType() 
    {
		return type;
	}
}
